/*
 * modify_structs.c
 * Zie modify_structs.h voor informatie over onderstaande functies.
 */



#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include "modify_structs.h"

entry_ptr string_create(const char *value) {
	entry_ptr entry = (entry_ptr)malloc(sizeof(entry_t));
	string_ptr str = (string_ptr)malloc(sizeof(string_t));
	char *charptr = (char*)malloc(strlen(value)+1);
	strcpy(charptr, value);

	/*
	 * In de huidige implementatie is string_t gewoon een charpointer,
	 * dus is het een kwestie van de pointer overdragen en teruggeven.
	 */
	*str = (string_t)charptr;

	entry->type = TYPE_STRING;
	entry->data.string = str;
	return entry;
}

entry_ptr integer_create(int value) {
	entry_ptr entry = (entry_ptr)malloc(sizeof(entry_t));
	integer_ptr i = (integer_ptr)malloc(sizeof(int));

	/*
	 * In de huidige implementatie is integer_t gewoon een int,
	 * dus moet simpelweg de int dezelfde waarde krijgen.
	 */
	*i = value;

	entry->type = TYPE_INTEGER;
	entry->data.integer = i;
	return entry;
}

entry_ptr dictionary_create() {
	/*
	 * Alloceer geheugen voor de entry_t en de dictionary_t.
	 * Zet vervolgens het entry-type goed en maak de dictionary leeg.
	 */
	entry_ptr entry = (entry_ptr)malloc(sizeof(entry_t));
	dictionary_ptr dict = (dictionary_ptr)malloc(sizeof(dictionary_t));
	dict->first = dict->last = NULL;

	entry->type = TYPE_DICTIONARY;
	entry->data.dictionary = dict;
	return entry;
}

entry_ptr list_create() {
	/*
	 * Alloceer geheugen voor de entry_t en de dictionary_t.
	 * Zet vervolgens het entry-type goed en maak de list leeg.
	 */
	entry_ptr entry = (entry_ptr)malloc(sizeof(entry_t));
	list_ptr list = (list_ptr)malloc(sizeof(list_t));
	list->first = list->last = NULL;

	entry->type = TYPE_LIST;
	entry->data.list = list;
	return entry;
}

entry_ptr dictionary_add(entry_ptr dict, const char *name, const entry_ptr entry) {
	if (dict->type != TYPE_DICTIONARY)
		return dict;

	/*
	 * Alloceer geheugen voor de naam van de nieuwe entry en de index.
	 * Koppel vervolgens de entry en naam aan de index en
	 * koppel de index aan de linked-list van de dictionary.
	 */
	char *charptr = (char*)malloc(strlen(name)+1);
	strcpy(charptr, name);

	dict_entry_ptr dict_e = (dict_entry_ptr)malloc(sizeof(dict_entry_t));
	dict_e->name = (string_t)charptr;
	dict_e->value = entry;
	dict_e->next = NULL;

	dictionary_ptr d = dict->data.dictionary;
	if (d->first == NULL) {
		d->first = d->last = dict_e;
	}
	else {
		d->last->next = dict_e;
		d->last = dict_e;
	}

	return dict;
}

entry_ptr list_add(entry_ptr list, const entry_ptr entry) {
	if (list->type != TYPE_LIST)
		return list;

	/*
	 * Alloceer geheugen voor de index.
	 * Koppel vervolgens de entry aan de index en koppel de index aan de linked-list van de list.
	 */
	list_entry_ptr list_e = (list_entry_ptr)malloc(sizeof(list_entry_t));
	list_e->value = entry;
	list_e->next = NULL;

	list_ptr l = list->data.list;
	if (l->first == NULL) {
		l->first = l->last = list_e;
	}
	else {
		l->last->next = list_e;
		l->last = list_e;
	}

	return list;
}

entry_ptr dictionary_find(entry_ptr dict, const string_t name) {
	entry_ptr entry = NULL;

	/*
	 * Doorloop de dictionary met een iterator en stop als er een index is gevonden met de gezochte naam.
	 */
	dict_entry_ptr it;
	for (it = dict->data.dictionary->first; it != NULL; it = it->next) {
		if (strcmp(name, it->name) == 0) {
			entry = it->value;
			break;
		}
	}

	return entry;
}

entry_ptr entry_destroy(entry_ptr entry) {
	switch (entry->type) {
	case TYPE_DICTIONARY:
	case TYPE_LIST:
		/* niet geïmplementeerd voor mappings en lijsten */
	break;

	case TYPE_STRING:
		free(entry->data.string);
		free(entry);
		entry = NULL;
	break;

	case TYPE_INTEGER:
		free(entry->data.integer);
		free(entry);
		entry = NULL;
	break;
	}
	return entry;
}


